﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Net;
using System.Threading;
using System.Net.NetworkInformation;

namespace WinMTR.NET
{

    class PingWorker : BackgroundWorker
    {
        public IPAddress Address { get; set; }
        public string Hostname { get; set; }

        public int SentPings { get; set; }
        public int RecvPings { get; set; }
        public long LastRoundTrip { get; set; }
        public long AvgRoundTrip { get; set; }
        public long BestRoundTrip { get; set; }
        public float Loss { get; set; }

        public int PingTimeout { get; private set; }
        public int PingInterval { get; private set; }
        public bool ResolveNames { get; private set; }
        public int TTL { get; set; }

        public RouteWorker RouteWorker { get; set; }


        public PingWorker(IPAddress address, int ttl, int pingTimeout, int pingInterval, bool resolveNames)
        {
            Address = address;
            PingTimeout = pingTimeout;
            PingInterval = pingInterval;
            ResolveNames = resolveNames;
            TTL = ttl;

            WorkerSupportsCancellation = true;
            WorkerReportsProgress = true;
            this.DoWork += new DoWorkEventHandler(PingWorker_DoWork);
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void PingWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            PingWorker w = (PingWorker)sender;
            Ping ping = new Ping();

            bool resolved = false;

            while (true && !w.CancellationPending)
            {
                if (!resolved && w.Address != null)
                {
                    Console.WriteLine("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++RESOLVE");
                    resolved = true;
                    Dns.BeginGetHostEntry(w.Address, ReverseCallback, w);
                }

                w.SentPings++;
                if (w.Address != null)
                {
                    PingReply reply = ping.Send(w.Address, w.PingTimeout);
                    if (reply.Status == IPStatus.Success)
                    {
                        w.RecvPings++;
                    }
                    w.AvgRoundTrip = (w.AvgRoundTrip + reply.RoundtripTime) / 2;
                    w.LastRoundTrip = reply.RoundtripTime;
                    w.BestRoundTrip = Math.Min(w.LastRoundTrip, w.BestRoundTrip);



                }
                w.Loss = ((float)(w.SentPings - w.RecvPings) / w.SentPings);
                //Console.WriteLine("         WORKER [{0}] [{1}]", w.Address, w.Loss);
                //lock (RouteWorker)
                //{
                //    RouteWorker.ShoudRefresh = true;
                //}
                Thread.Sleep(w.PingInterval);


            }
        }


        private static void ReverseCallback(IAsyncResult r)
        {
            try
            {
                PingWorker w = (PingWorker)r.AsyncState;
                IPHostEntry ihe = Dns.EndGetHostEntry(r);
                if (ihe != null)
                {
                    w.Hostname = ihe.HostName;
                }

            }
            catch { }
        }



    }

}
